package com.geekhole.demo.user.domain;

import com.google.common.base.Preconditions;
import lombok.AccessLevel;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

@Data
@Setter(AccessLevel.PRIVATE)
@Entity
@Table
public class User implements Agg{
    @Transient
    @Getter(AccessLevel.PRIVATE)
    private final List<Object> events = new ArrayList<>();

    @Id
    @GeneratedValue
    private Long id;

    private String name;

    private Integer age;

    private UserStatus status;


    public static User create(String name, Integer age) {
        Preconditions.checkArgument(StringUtils.isNotEmpty(name));
        Preconditions.checkArgument(age != null && age > 0);

        User user = new User();
        user.setName(name);
        user.setAge(age);

        UserCreatedEvent event = UserCreatedEvent.builder()
                .age(user.getAge())
                .name(user.getName())
                .build();
        user.publishEvent(event);
        return user;
    }

    public void enable(){
        setStatus(UserStatus.ENABLE);
        UserEnabledEvent event = UserEnabledEvent.builder()
                .userId(getId())
                .build();
        publishEvent(event);
    }

    public void modifyUserName(String newName){
        Preconditions.checkArgument(StringUtils.isNoneBlank(newName));

        String oldName = getName();

        setName(newName);

        UserNameModifiedEvent event = UserNameModifiedEvent.builder()
                .userId(getId())
                .oldName(oldName)
                .newName(newName)
                .build();
        publishEvent(event);
    }

    protected void publishEvent(Object event){
        this.events.add(event);
    }

    @Override
    public void foreachEvent(Consumer<Object> consumer){
        this.events.forEach(consumer);
    }

    @Override
    public void clearEvents(){
        this.events.clear();
    }

}
